home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_sys5 / unixkit.tgz / unixkit.tar / unixkit / common / bsd_tun.c < prev    next >
C/C++ Source or Header  |  1991-12-05  |  6KB  |  219 lines

  1. /* This is a very early release of a Tunnel driver for 4.3 BSD systems.
  2.  * You need to run this program as root. Please think about security
  3.  * during shell escapes, ftp-sessions etc.
  4.  * Define PACKET in config.h to use this driver.
  5.  *
  6.  * On your UNIX system, you will have to issue the following command
  7.  * to activate the tunnel interface:
  8.  *     ifconfig tun0 <unix-hostname> <nos-hostname>
  9.  *
  10.  * A corrected version of the Tunnel driver is available with ftp
  11.  * from sics.se.
  12.  *
  13.  * SM0RGV
  14.  *
  15.  * KA9WSB - argv[3] is now used to select the tunnel device number...
  16.  * this allows easier debug!
  17.  *
  18.  * KA9WSB - code added to reset the user id immediately after attaching
  19.  * the device.  This allows us to run NOS as a setuid program, and have
  20.  * it relinquish root privs as soon as it no longer needs them!
  21.  */
  22. #include <stdio.h>
  23. #include <sys/types.h>
  24. #include <sys/time.h>
  25. #include <sys/param.h>
  26. #include <sys/stropts.h>
  27. #include <sys/file.h>
  28. #include <sys/ioctl.h>
  29. #include <sys/socket.h>
  30. #include <net/if.h>
  31. #include "if_tnreg.h"
  32. #include "global.h"
  33. #include "config.h"
  34. #include "mbuf.h"
  35. #include "iface.h"
  36. #include "netuser.h"
  37. #include "slip.h"
  38. #include "pktdrvr.h"
  39. #include "asy.h"
  40. struct tundrvr Tundrvr[TUN_MAX];
  41. int tun_raw(),tun_stop();
  42. void tun_input();
  43.  
  44. extern struct iface *Ifaces;
  45. extern struct mbuf *Hopper;
  46. extern char Nospace[];
  47. int Ntun;
  48. /* Define some NIT stuff to keep the compiler happy */
  49. struct nitdrvr Nitdrvr[NIT_MAX];
  50. int Nnit;
  51.  
  52. /* Attach a packet driver to the system
  53.  * argv[0]: hardware type, must be "packet"
  54.  * argv[1]: destination address
  55.  * argv[2]: interface label, same as real interface, e.g., "tun0"
  56.  * argv[3]: The tunnel device number; i.e. 0 == /dev/tun0, 1 == /dev/tun1
  57.  * argv[4]: maximum transmission unit, bytes, e.g., "1500"
  58.  * argv[5]: optional source IP address
  59.  */
  60. pk_attach(argc,argv,p)
  61. int argc;
  62. char **argv;
  63. void *p;
  64. {
  65.     struct ifreq   ifr;
  66.     struct iface *if_tun;
  67.     struct tundrvr *pp;
  68.     char tundevice[16];
  69.     int i,val,if_flags;
  70.       
  71.     if(Ntun >= TUN_MAX){
  72.     tprintf("Too many tunnel drivers\n");
  73.     return -1;
  74.     }
  75.     if(if_lookup(argv[2]) != NULLIF){
  76.     tprintf("Interface %s already exists\n",argv[2]);
  77.     return -1;
  78.     }
  79.     if_tun = (struct iface *)callocw(1,sizeof(struct iface));
  80.     if_tun->name = strdup(argv[2]);
  81.     
  82.     if(argc > 5)
  83.     if_tun->addr = resolve(argv[5]);
  84.     else
  85.     if_tun->addr = Ip_addr;
  86.     if(if_tun->addr == 0){
  87.     tprintf(Noipaddr);
  88.     free((char *)if_tun);
  89.     return -1;
  90.     }
  91.     pp = &Tundrvr[Ntun];
  92.     if_tun->mtu = atoi(argv[4]);
  93.     if_tun->dev = Ntun;
  94.     setencap(if_tun,"None");
  95.     if_tun->raw = tun_raw;
  96.     if_tun->stop = tun_stop;
  97.     pp->iface = if_tun;
  98.     if_tun->send = slip_send;
  99.     if_tun->output = NULLFP;
  100.     if_tun->type = CL_NONE;
  101.  
  102.     sprintf(tundevice,"/dev/tun%s",argv[3]);
  103.  
  104.     if((pp->IOser = open(tundevice, O_RDWR)) == -1) {
  105.     tprintf("Can't open %s\n",tundevice);
  106.     free((char *)if_tun);
  107.     return -1;
  108.     }
  109.  
  110.     /* Configure the tun device, binding it to the proper
  111.        underlying interface */
  112. /*    strncpy(ifr.ifr_name, argv[2], sizeof ifr.ifr_name);*/
  113.  
  114.     /* Enable interrupt for input to an empty queue */
  115.     val = -getpid();
  116.     ioctl(pp->IOser,TIOCSPGRP,&val);
  117.     val = 1;
  118.     ioctl(pp->IOser,FIOASYNC,&val);
  119.     ioctl(pp->IOser,FIONBIO,&val); /* non-blocking mode */
  120.  
  121.     /* Flush the read queue, to get rid of anything that accumulated
  122.        before the device reached its final configuration. */
  123. /*    ioctl(pp->IOser, I_FLUSH, (char *)FLUSHR);*/
  124.     if_tun->next = Ifaces;
  125.     Ifaces = if_tun;
  126.     newproc("tunnel_rx",2048,tun_input,0,(void *)pp,NULL,0);
  127.     tprintf("Attached %s\n",argv[2]);
  128.     ++Ntun;
  129.     seteuid(getuid());    /* reset any SETUID privs we might have! KA9WSB */
  130.     return 0;
  131. }
  132. /* This is the task that takes care of incoming IP packets.
  133.    It would be better to do all this at interrupt level (ie from inpint)
  134.    but the program seems to crash if you do memory allocation operations
  135.    from interrupt level without using alloc.c
  136. */
  137. void tun_input(unused,arg,unused2)
  138. void *arg;
  139. void *unused2;
  140. {
  141.     int res;
  142.     struct mbuf *bp;
  143.     struct phdr *phdr;
  144.     char buf[TUNMTU], i_state;
  145.     struct tundrvr *pp;
  146.  
  147.     pp = (struct tundrvr *) arg;
  148.     for (;;) {
  149.         /* If there are no new messages to fetch from the tun interface,
  150.          * then wait until inpint() gives you a signal.
  151.          */
  152.         res = 0;
  153.         ioctl(pp->IOser,FIONREAD,&res);    /* Find how much to read */
  154.         if(res == 0) {
  155.         i_state = dirps();
  156.         pwait(pp);
  157.         restore(i_state);
  158.         continue;
  159.         }
  160.         res = read(pp->IOser,buf,TUNMTU);
  161.         if (res == -1){
  162.         perror("read");
  163.         continue;
  164.         }
  165.  
  166.         /* Process the packet. */
  167.         if((bp = alloc_mbuf(res+sizeof(struct phdr))) == NULLBUF){
  168.         tprintf(Nospace);
  169.         continue;
  170.         }
  171.         memcpy(bp->data+sizeof(struct phdr),buf,res);
  172.         /* Generate descriptor header */
  173.         phdr = (struct phdr *)bp->data;
  174.         phdr->iface = pp->iface;
  175.         phdr->type = CL_NONE;
  176.         bp->cnt = res + sizeof(struct phdr);
  177.         enqueue(&Hopper,bp);
  178.     }
  179. }
  180. /* Send raw packet (caller provides header) */
  181. int
  182. tun_raw(iface,bp)
  183. struct iface *iface;    /* Pointer to interface control block */
  184. struct mbuf *bp;        /* Data field */
  185. {
  186.     register struct tundrvr *pp;
  187.     struct mbuf *bp1;
  188.     short size;
  189.     char i_state;
  190.  
  191.     pp = &Tundrvr[iface->dev];
  192.  
  193. /*    pp->stats.xmit++;*/
  194.  
  195.     size = len_p(bp);
  196.  
  197.     if(bp->next != NULLBUF){
  198.     /* Copy to contiguous buffer, since driver can't handle mbufs */
  199.         bp1 = copy_p(bp,size);
  200.         free_p(bp);
  201.         bp = bp1;
  202.         if(bp == NULLBUF)
  203.             return -1;
  204.     }
  205.  
  206.     dump(iface,IF_TRACE_OUT,CL_NONE,bp);
  207.  
  208.     i_state = dirps();
  209.     write(pp->IOser,bp->data,size);
  210.     restore(i_state);
  211.     free_p(bp);
  212.     return 0;
  213. }
  214.  
  215. int
  216. tun_stop()
  217. {
  218. }
  219.